package com.bonc.modules.item.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bonc.datasource.annotation.DataSource;
import com.bonc.modules.item.dao.ItemValueDao;
import com.bonc.modules.item.entity.ItemNodeEntity;
import com.bonc.modules.item.entity.ItemValueEntity;
import com.bonc.modules.item.param.ItemValueParam;
import com.bonc.modules.item.result.ItemChartDataResult;
import com.bonc.modules.item.service.ItemNodeService;
import com.bonc.modules.item.service.ItemValueService;
import com.bonc.modules.item.utils.ChartDate;
import com.bonc.modules.item.utils.ChartDateTypeEnum;
import com.bonc.modules.item.utils.ChartDateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author jinlong
 * @date 2021/8/9
 */
@DataSource("gbasedata")
@Service
public class ItemValueServiceImpl extends ServiceImpl<ItemValueDao, ItemValueEntity> implements ItemValueService {

    @Autowired
    private ItemNodeService itemNodeService;

    /**
     * 获取文本数据
     *
     * @param itemValueParam 指标中心图数据查询参数
     */
    @Override
    public ItemValueEntity getTextData(ItemValueParam itemValueParam) {
        LambdaQueryWrapper<ItemValueEntity> queryWrapper = new LambdaQueryWrapper<>();
        // 日期
        if (ObjectUtil.isNotEmpty(itemValueParam.getDealDate()) && ObjectUtil.isNotEmpty(itemValueParam.getDateType())) {
            ChartDate chartDate = ChartDateUtils.getEnd(itemValueParam.getDealDate(), itemValueParam.getDateType());
            queryWrapper.eq(ItemValueEntity::getDealDate, chartDate);
        }
        // 地市
        if (ObjectUtil.isNotEmpty(itemValueParam.getCityCode())) {
            queryWrapper.eq(ItemValueEntity::getRegionCode, itemValueParam.getCityCode());
        } else {
            queryWrapper.eq(ItemValueEntity::getRegionCode, "00");
        }
        // 区县
        if (ObjectUtil.isNotEmpty(itemValueParam.getCountyCode())) {
            queryWrapper.eq(ItemValueEntity::getCityCode, itemValueParam.getCountyCode());
        } else {
            queryWrapper.eq(ItemValueEntity::getCityCode, "00");
        }
        // 网格
        if (ObjectUtil.isNotEmpty(itemValueParam.getGridCode())) {
            queryWrapper.eq(ItemValueEntity::getGriddingCode, itemValueParam.getGridCode());
        } else {
            queryWrapper.eq(ItemValueEntity::getGriddingCode, "00");
        }

        queryWrapper.eq(ItemValueEntity::getItemCode, itemValueParam.getItemCode());
        queryWrapper.eq(ItemValueEntity::getDimId, itemValueParam.getDimId());
        queryWrapper.eq(ItemValueEntity::getGroupCode, itemValueParam.getGroupCode());
        return this.getOne(queryWrapper);
    }


    /**
     * 获取趋势图数据
     *
     * @param chartDateParam 指标中心图数据查询参数
     */
    @Override
    public ItemChartDataResult getLineChart(ItemValueParam chartDateParam) {
        LambdaQueryWrapper<ItemValueEntity> queryWrapper = new LambdaQueryWrapper<>();
        List<ChartDate> dateList = new ArrayList<>();
        // 日期
        if (ObjectUtil.isNotEmpty(chartDateParam.getDealDate()) && ObjectUtil.isNotEmpty(chartDateParam.getDateType())) {
            dateList = ChartDateUtils.getRecent(chartDateParam.getDealDate(), chartDateParam.getDateType());
            queryWrapper.in(ItemValueEntity::getDealDate, dateList);
        }
        // 地市
        if (ObjectUtil.isNotEmpty(chartDateParam.getCityCode())) {
            queryWrapper.eq(ItemValueEntity::getRegionCode, chartDateParam.getCityCode());
        } else {
            queryWrapper.eq(ItemValueEntity::getRegionCode, "00");
        }
        // 区县
        if (ObjectUtil.isNotEmpty(chartDateParam.getCountyCode())) {
            queryWrapper.eq(ItemValueEntity::getCityCode, chartDateParam.getCountyCode());
        } else {
            queryWrapper.eq(ItemValueEntity::getCityCode, "00");
        }
        // 网格
        if (ObjectUtil.isNotEmpty(chartDateParam.getGridCode())) {
            queryWrapper.eq(ItemValueEntity::getGriddingCode, chartDateParam.getGridCode());
        } else {
            queryWrapper.eq(ItemValueEntity::getGriddingCode, "00");
        }

        queryWrapper.eq(ItemValueEntity::getItemCode, chartDateParam.getItemCode());
        queryWrapper.eq(ItemValueEntity::getDimId, chartDateParam.getDimId());
        queryWrapper.eq(ItemValueEntity::getGroupCode, chartDateParam.getGroupCode());
        queryWrapper.orderByAsc(ItemValueEntity::getDealDate);
        List<ItemValueEntity> list = this.list(queryWrapper);
        return this.trendConvert(chartDateParam.getDateType(), dateList, list);
    }

    @Override
    public ItemChartDataResult getRegionChart(ItemValueParam chartDateParam) {

        String regionStaticCode = "00";
        int regionType = 0;


        QueryWrapper<ItemValueEntity> queryWrapper = new QueryWrapper<>();
        // 日期
        ChartDate chartDate;
        if (ObjectUtil.isNotEmpty(chartDateParam.getDealDate()) && ObjectUtil.isNotEmpty(chartDateParam.getDateType())) {
            chartDate = ChartDateUtils.getEnd(chartDateParam.getDealDate(), chartDateParam.getDateType());
            queryWrapper.eq("t1.deal_date", chartDate);
        }
        // 区域
        if (ObjectUtil.isNotEmpty(chartDateParam.getGridCode()) && !regionStaticCode.equals(chartDateParam.getGridCode())) {
            // 同级网格
            regionType = 2;
            queryWrapper.eq("t1.region_code", chartDateParam.getCityCode());
            queryWrapper.eq("t1.city_code", chartDateParam.getCountyCode());
            queryWrapper.ne("t1.gridding_code", regionStaticCode);
        } else if (ObjectUtil.isNotEmpty(chartDateParam.getCountyCode()) && !regionStaticCode.equals(chartDateParam.getCountyCode())) {
            // 同级区县
            regionType = 1;
            queryWrapper.eq("t1.region_code", chartDateParam.getCityCode());
            queryWrapper.ne("t1.city_code", regionStaticCode);
            queryWrapper.eq("t1.gridding_code", regionStaticCode);
        } else {
            // 同级地市
            regionType = 0;
            queryWrapper.notIn("t1.region_code", "00", "99");
            queryWrapper.eq("t1.city_code", regionStaticCode);
            queryWrapper.eq("t1.gridding_code", regionStaticCode);
        }
        queryWrapper.eq("t1.item_code", chartDateParam.getItemCode());
        queryWrapper.eq("t1.dim_id", chartDateParam.getDimId());
        queryWrapper.eq("t1.group_code", chartDateParam.getGroupCode());
        queryWrapper.orderByAsc("t1.region_code", "t1.city_code", "t1.gridding_code");
        List<ItemValueEntity> list = this.baseMapper.list(queryWrapper);
        return this.convert(chartDateParam.getDateType(), regionType, list);
    }

    @Override
    public ItemChartDataResult getGroupChart(ItemValueParam chartDateParam) {
        ItemNodeEntity itemNodeEntity = new ItemNodeEntity();
        itemNodeEntity.setBizType(chartDateParam.getGroupCode());
        List<ItemNodeEntity> nodeEntityList;
        ItemNodeEntity curItemNode = itemNodeService.curItemNode(itemNodeEntity);
        if (ObjectUtil.isEmpty(chartDateParam.getFlag())) {
            nodeEntityList = itemNodeService.listChildren(itemNodeEntity);
        } else {
            nodeEntityList = itemNodeService.listBros(itemNodeEntity);
        }

        LambdaQueryWrapper<ItemValueEntity> queryWrapper = new LambdaQueryWrapper<>();
        // 日期
        ChartDate chartDate;
        if (ObjectUtil.isNotEmpty(chartDateParam.getDealDate()) && ObjectUtil.isNotEmpty(chartDateParam.getDateType())) {
            chartDate = ChartDateUtils.getEnd(chartDateParam.getDealDate(), chartDateParam.getDateType());
            queryWrapper.eq(ItemValueEntity::getDealDate, chartDate);
        }
        // 地市
        if (ObjectUtil.isNotEmpty(chartDateParam.getCityCode())) {
            queryWrapper.eq(ItemValueEntity::getRegionCode, chartDateParam.getCityCode());
        } else {
            queryWrapper.eq(ItemValueEntity::getRegionCode, "00");
        }
        // 区县
        if (ObjectUtil.isNotEmpty(chartDateParam.getCountyCode())) {
            queryWrapper.eq(ItemValueEntity::getCityCode, chartDateParam.getCountyCode());
        } else {
            queryWrapper.eq(ItemValueEntity::getCityCode, "00");
        }
        // 网格
        if (ObjectUtil.isNotEmpty(chartDateParam.getGridCode())) {
            queryWrapper.eq(ItemValueEntity::getGriddingCode, chartDateParam.getGridCode());
        } else {
            queryWrapper.eq(ItemValueEntity::getGriddingCode, "00");
        }

        queryWrapper.eq(ItemValueEntity::getItemCode, chartDateParam.getItemCode());
        queryWrapper.eq(ItemValueEntity::getDimId, chartDateParam.getDimId());
        queryWrapper.in(ItemValueEntity::getGroupCode, nodeEntityList.stream().map(ItemNodeEntity::getBizType).collect(Collectors.toList()));
        queryWrapper.orderByAsc(ItemValueEntity::getGroupCode);
        List<ItemValueEntity> list = this.list(queryWrapper);
        return this.convert(chartDateParam.getDateType(), nodeEntityList, curItemNode, list);
    }


    /**
     * 趋势图数据转换
     *
     * @param dateTypeEnum      日期类型
     * @param dateList          日期列表
     * @param chartDataEntities 数据实体列表
     * @return
     */
    private ItemChartDataResult trendConvert(ChartDateTypeEnum dateTypeEnum, List<ChartDate> dateList, List<ItemValueEntity> chartDataEntities) {
        String dateFormat = "yyyy-MM-dd";

        List<String> xSeries = new ArrayList<>();
        List<Number> dataList = new ArrayList<>();
        Map<String, Number> dataMap;
        switch (dateTypeEnum) {
            case MONTH:
                dataMap = chartDataEntities.stream()
                        .collect(Collectors.toMap(itemValueEntity -> DateUtil.format(itemValueEntity.getDealDate(), dateFormat), ItemValueEntity::getMonValue));
                break;
            case QUARTER:
                dataMap = chartDataEntities.stream()
                        .collect(Collectors.toMap(itemValueEntity -> DateUtil.format(itemValueEntity.getDealDate(), dateFormat), ItemValueEntity::getQuarterValue));
                break;
            case YEAR:
                dataMap = chartDataEntities.stream()
                        .collect(Collectors.toMap(itemValueEntity -> DateUtil.format(itemValueEntity.getDealDate(), dateFormat), ItemValueEntity::getYearValue));
                break;
            default:
                dataMap = chartDataEntities.stream()
                        .collect(Collectors.toMap(itemValueEntity -> DateUtil.format(itemValueEntity.getDealDate(), dateFormat), ItemValueEntity::getDayValue));
                break;
        }
        for (ChartDate date : dateList) {
            xSeries.add(date.toString());
            dataList.add(dataMap.get(DateUtil.format(date, dateFormat)));

        }
        return new ItemChartDataResult(xSeries, dataList);
    }

    /**
     * 地市排名数据转换
     *
     * @param dateTypeEnum      日期类型
     * @param regionType        区域类型
     * @param chartDataEntities 数据实体列表
     * @return
     */
    private ItemChartDataResult convert(ChartDateTypeEnum dateTypeEnum, int regionType, List<ItemValueEntity> chartDataEntities) {

        List<String> xAxis;
        List<Number> dataList;
        switch (dateTypeEnum) {
            case MONTH:
                dataList = chartDataEntities.stream().map(ItemValueEntity::getMonValue).collect(Collectors.toList());
                break;
            case QUARTER:
                dataList = chartDataEntities.stream().map(ItemValueEntity::getQuarterValue).collect(Collectors.toList());
                break;
            case YEAR:
                dataList = chartDataEntities.stream().map(ItemValueEntity::getYearValue).collect(Collectors.toList());
                break;
            default:
                dataList = chartDataEntities.stream().map(ItemValueEntity::getDayValue).collect(Collectors.toList());
                break;
        }
        switch (regionType) {
            case 1:
                // TODO 上线改为ItemValueEntity::getCityName
                xAxis = chartDataEntities.stream().map(ItemValueEntity::getCityCode).collect(Collectors.toList());
                break;
            case 2:
                // TODO 上线改为ItemValueEntity::getGriddingName
                xAxis = chartDataEntities.stream().map(ItemValueEntity::getGriddingCode).collect(Collectors.toList());
                break;
            default:
                // TODO 上线改为ItemValueEntity::getRegionName
                xAxis = chartDataEntities.stream().map(ItemValueEntity::getRegionCode).collect(Collectors.toList());
                break;
        }
        return new ItemChartDataResult(xAxis, dataList);
    }

    /**
     * 业务分类数据转换
     *
     * @param dateTypeEnum      日期类型
     * @param nodeEntityList    业务分类列表
     * @param chartDataEntities 数据实体列表
     * @return
     */
    private ItemChartDataResult convert(ChartDateTypeEnum dateTypeEnum, List<ItemNodeEntity> nodeEntityList, ItemNodeEntity curItemNode, List<ItemValueEntity> chartDataEntities) {

        List<String> xAxis = nodeEntityList.stream().map(ItemNodeEntity::getBizName).collect(Collectors.toList());
        List<Map> dataList = new ArrayList<>();
        Map<String, ItemValueEntity> dataMap = chartDataEntities.stream().collect(Collectors.toMap(ItemValueEntity::getGroupCode, itemValueEntity -> itemValueEntity));

        for (ItemNodeEntity nodeEntity : nodeEntityList) {
            HashMap<String, Object> map = new HashMap<>(16);
            map.put("name", nodeEntity.getBizName());
            map.put("code", nodeEntity.getBizType());
            ItemValueEntity itemValueEntity = MapUtil.get(dataMap, nodeEntity.getBizType(), ItemValueEntity.class);
            if (ObjectUtil.isNull(itemValueEntity)) {
                map.put("value", null);
            } else {
                switch (dateTypeEnum) {
                    case MONTH:
                        map.put("value", itemValueEntity.getMonValue());
                        break;
                    case QUARTER:
                        map.put("value", itemValueEntity.getQuarterValue());
                        break;
                    case YEAR:
                        map.put("value", itemValueEntity.getYearValue());
                        break;
                    default:
                        map.put("value", itemValueEntity.getDayValue());
                        break;
                }
            }

            dataList.add(map);
        }
        return new ItemChartDataResult(dataList, curItemNode.getParentBizType());
    }
}
